{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "14c01af2-d331-4aa4-9639-41353601a767",
   "metadata": {},
   "source": [
    "# Jacobi stencil\n",
    "\n",
    "<details>\n",
    "<summary>License</summary>\n",
    "<pre>\n",
    "\n",
    "Copyright 2023 NVIDIA Corporation\n",
    "\n",
    "Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "you may not use this file except in compliance with the License.\n",
    "You may obtain a copy of the License at\n",
    "\n",
    "     http://www.apache.org/licenses/LICENSE-2.0\n",
    "\n",
    "Unless required by applicable law or agreed to in writing, software\n",
    "distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "See the License for the specific language governing permissions and\n",
    "limitations under the License.\n",
    "</pre>\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35c48e6f-1bde-4aac-af55-b7218cc22491",
   "metadata": {},
   "source": [
    "To get started, `import cunumeric as np` (just the same way we would import `numpy`)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "bfc50224-f762-4ec0-8ded-671cbd1df559",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import cunumeric as np  # instead of numpy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6dbc790d-f337-4ae7-93e2-3ec90f174a8d",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Because of Legate's deferred execution model, legate.timing should be used instead\n",
    "# of standard Python datetime utilities. Python datetime.now would return the time\n",
    "# a task is *scheduled*, not necessarily the time a task finishes executing.\n",
    "from legate.timing import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3df09ac1-0791-4215-8dc6-82fd8ab34960",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def jacobi(grid, I): \n",
    "    print(\"Running Jacobi stencil... \", end=\"\")\n",
    "    \n",
    "    center = grid[1:-1, 1:-1]\n",
    "    north = grid[0:-2, 1:-1]\n",
    "    east = grid[1:-1, 2:]\n",
    "    west = grid[1:-1, 0:-2]\n",
    "    south = grid[2:, 1:-1]\n",
    "\n",
    "    start = time()\n",
    "    for i in range(I):\n",
    "        average = center + north + east + west + south\n",
    "        center[:] = 0.2 * average\n",
    "    stop = time()\n",
    "\n",
    "    print(f\"Elapsed Time: {(stop - start)/1000} ms\")\n",
    "    \n",
    "    return grid"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89a51f9e-d311-44f8-b54e-2a64057502f3",
   "metadata": {},
   "source": [
    "We also want to define a small helper function `make_grid` to generate a test grid for us to use"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "accbfd3d-a691-47ab-b022-754109555859",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def make_grid(N):\n",
    "    grid = np.zeros((N + 2, N + 2))\n",
    "    grid[:, 0] = -273.15\n",
    "    grid[:, -1] = -273.15\n",
    "    grid[-1, :] = -273.15\n",
    "    grid[0, :] = 40.0\n",
    "    return grid"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c1fbd69-6a65-4359-b1be-80c76e99c9ab",
   "metadata": {},
   "source": [
    "Let's first create a grid using `make_grid`, and see what it looks like using Matplotlib's `pcolor` function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "24a832e3-fe8e-4ae3-a168-35b20438c7bc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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AAD0Ub0WK5WVlZo8ebICgUDU/qamJnV0dETtLywsVF5enhoaGi54rfb2doXD4agNAAAMDEm9cdENGzbovffe0+7du887FgwGlZycrPT09Kj9Pp9PwWDwgterra3Vo48+2hujAgAA42L+zEpLS4vmzJmjdevWKSUlJSbXrK6uVigUimwtLS0xuS4AALAv5rHS1NSk48eP67rrrlNSUpKSkpK0fft2LV++XElJSfL5fDp79qza2tqi7tfa2iq/33/Ba3o8HqWlpUVtAABgYIj5r4EmTJigDz74IGrfjBkzVFhYqIceeki5ubkaPHiw6uvrVVpaKklqbm7W0aNHVVJSEutxAABAHxfzWBk6dKhGjhwZte/iiy9WZmZmZP/MmTM1b948ZWRkKC0tTffff79KSkp04403xnocAADQx/XKC2z/N0899ZQSExNVWlqq9vZ2TZw4UU8//XQ8RgEAAMYlOOdcvIfoqXA4LK/Xq5s0RUkJgyVJFYcOx3kqAADwVasLLo+6fc516G29olAo1KPXn/K3gQAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTiBUAAGAasQIAAEwjVgAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTiBUAAGAasQIAAEwjVgAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTiBUAAGAasQIAAEwjVgAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTiBUAAGAasQIAAEwjVgAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTiBUAAGAasQIAAEwjVgAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTiBUAAGAasQIAAEwjVgAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTiBUAAGAasQIAAEwjVgAAgGnECgAAMI1YAQAAphErAADANGIFAACYRqwAAADTYh4rtbW1uv766zV06FBlZWVp6tSpam5ujjrnzJkzqqysVGZmpoYMGaLS0lK1trbGehQAANAPxDxWtm/frsrKSu3cuVNbt25VR0eHfvjDH+r06dORc+bOnavXXntNGzdu1Pbt23Xs2DFNmzYt1qMAAIB+ICnWF9yyZUvU7eeff15ZWVlqamrS9773PYVCIT377LNav369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XV2SWIN46M5jXlJSora2NjU1NUXO2bZtm7q6ulRcXNz9L/Yfvzz4W7Zhwwbn8Xjc888/7w4cOOAqKipcenq6CwaD8R6tX7r33nud1+t1b7/9tvvss88i2xdffBE555577nF5eXlu27Ztbs+ePa6kpMSVlJTEcer+76vvBnKONehtu3btcklJSW7RokXu0KFDbt26de6iiy5yf/rTnyLnLF682KWnp7tXXnnF/e1vf3NTpkzhbbMxVF5e7r7zne9E3rr88ssvu0svvdTNnz8/cg5rEHsnT550e/fudXv37nWS3NKlS93evXvdJ5984pzr3mN+yy23uNGjR7vGxka3Y8cOV1BQ0P/fuuyccytWrHB5eXkuOTnZ3XDDDW7nzp3xHqnfknTBbc2aNZFzvvzyS3ffffe5Sy65xF100UXuxz/+sfvss8/iN/QA8PVYYQ1632uvveZGjhzpPB6PKywsdKtXr4463tXV5WpqapzP53Mej8dNmDDBNTc3x2na/iccDrs5c+a4vLw8l5KS4i6//HL38MMPu/b29sg5rEHsvfXWWxf8GVBeXu6c695j/s9//tPdcccdbsiQIS4tLc3NmDHDnTx5skdzJDj3lY//AwAAMKZPvWYFAAAMPMQKAAAwjVgBAACmESsAAMA0YgUAAJhGrAAAANOIFQAAYBqxAgAATCNWAACAacQKAAAwjVgBAACmESsAAMC0/wtzoJFS5gEjnwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "G = make_grid(100)\n",
    "\n",
    "plt.pcolor(G);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f441193f-b8b9-4105-836c-5338902c9c4d",
   "metadata": {},
   "source": [
    "As we can see it produces a two dimensional array of zeros with some different values on the boundaries. Now let's run 1000 iterations of our Jacobi stencil on this image and look at the result."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3e8cc5c7-d38b-4072-a50e-33e81fc64ae1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running Jacobi stencil... Elapsed Time: 2461.875 ms\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "G = jacobi(G, 1000)\n",
    "\n",
    "plt.pcolor(G);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00462ab3-ba0d-4e71-a587-93b12ca37e34",
   "metadata": {},
   "source": [
    "We can see that the effect of running the stencil over the image repeatedly is to average out all the pixels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae92e7d2-8d25-4ef1-85ff-1681a8833f72",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
